package com.example.demo.util;
import org.apache.commons.lang.StringUtils;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CPUUtil extends HttpServlet {

    public static Map<Object,Object> printlnCpuInfo() throws InterruptedException {
        SystemInfo systemInfo = new SystemInfo();
        CentralProcessor processor = systemInfo.getHardware().getProcessor();
        long[] prevTicks = processor.getSystemCpuLoadTicks();
        // 睡眠1s
        TimeUnit.SECONDS.sleep(1);
        long[] ticks = processor.getSystemCpuLoadTicks();
        long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
        long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
        long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
        long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
        long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
        long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
        long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
        long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
        long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
        double cpuTemperature = systemInfo.getHardware().getSensors().getCpuTemperature();

        Map<Object,Object> res = new HashMap<>();
        res.put("cpu_cores",processor.getLogicalProcessorCount());
        res.put("cpu_sys_used_rate",new DecimalFormat("#.#%").format(cSys * 1.0 / totalCpu));
        res.put("cpu_user_used_rate",new DecimalFormat("#.#%").format(user * 1.0 / totalCpu));
        res.put("cpu_wait_rate",new DecimalFormat("#.#%").format(iowait * 1.0 / totalCpu));
        res.put("cpu_sum_used_rate",new DecimalFormat("#.#%").format(1.0-(idle * 1.0 / totalCpu)));
        res.put("cpu_degree",cpuTemperature);
        return res;
    }

    public static Map<Object,Object> MemInfo() {
        SystemInfo systemInfo = new SystemInfo();
        GlobalMemory memory = systemInfo.getHardware().getMemory();
        //总内存
        long totalByte = memory.getTotal();
        //剩余
        long acaliableByte = memory.getAvailable();
        Properties props = System.getProperties();
        //系统名称
        String osName = props.getProperty("os.name");
        //架构名称
        String osArch = props.getProperty("os.arch");
        Map<Object,Object> res = new HashMap<>();

        InetAddress addr = null;
        try {
            addr = InetAddress.getLocalHost();
        }catch (Exception e){
            e.printStackTrace();
        }
        String ip = addr.getHostAddress();
        String hostname = addr.getHostName();
        res.put("ip",ip);
        res.put("hostname",hostname);
        res.put("sys_name",osName);
        res.put("sys_arch",osArch);
        res.put("mem_total",formatByte(totalByte));
        res.put("mem_used",formatByte(totalByte-acaliableByte));
        res.put("mem_left",formatByte(acaliableByte));
        res.put("mem_use_rate",new DecimalFormat("#.#%").format((totalByte-acaliableByte)*1.0/totalByte));
        return res;
    }

    public static String getMacInWindows(final String ip){
        String result = "";
        String[] cmd = {"cmd", "/c", "ping " + ip};
        String[] another = {"cmd", "/c", "arp -a"};
        String cmdResult = callCmd(cmd,another);
        result = filterMacAddress(ip,cmdResult,"-");
        return result;
    }

    public static String callCmd(String[] cmd,String[] another) {
        String result = "";
        String line = "";
        try {
            Runtime rt = Runtime.getRuntime();
            Process proc = rt.exec(cmd);
            // 已经执行完第一个命令，准备执行第二个命令
            proc.waitFor();
            proc = rt.exec(another);
            InputStreamReader is = new InputStreamReader(proc.getInputStream());
            BufferedReader br = new BufferedReader(is);
            while ((line = br.readLine ()) != null) {
                result += line;
            }
        }catch(Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static String filterMacAddress(final String ip, final String sourceString,final String macSeparator) {
        String result = "";
        String regExp = "((([0-9,A-F,a-f]{1,2}" + macSeparator + "){1,5})[0-9,A-F,a-f]{1,2})";
        Pattern pattern = Pattern.compile(regExp);
        Matcher matcher = pattern.matcher(sourceString);
        while(matcher.find()){
            result = matcher.group(1);
            // 如果有多个IP,只匹配本IP对应的Mac.
            if(sourceString.indexOf(ip) <= sourceString.lastIndexOf(matcher.group(1))){
                break;
            }
        }
        return result;
    }

    public static String formatByte(long byteNumber){
        //换算单位
        double FORMAT = 1024.0;
        double kbNumber = byteNumber/FORMAT;
        if(kbNumber<FORMAT){
            return new DecimalFormat("#.#K").format(kbNumber);
        }
        double mbNumber = kbNumber/FORMAT;
        if(mbNumber<FORMAT){
            return new DecimalFormat("#.#M").format(mbNumber);
        }
        double gbNumber = mbNumber/FORMAT;
        if(gbNumber<FORMAT){
            return new DecimalFormat("#.#G").format(gbNumber);
        }
        double tbNumber = gbNumber/FORMAT;
        return new DecimalFormat("#.#T").format(tbNumber);
    }
}
